package com.automapper.interceptor;

import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.CachingExecutor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.SimpleExecutor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.automapper.executor.AutoMapperBatchExecutor;
import com.automapper.utils.MetaObjectUtils;

/**
 * 在ExecutorType.SIMPLE模式下替换原来的SimpleExecutor对象，实现批量入库操作。
 * 注意：现在只支持批量update
 * @author K
 *
 */
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class })})
public class AutoMapperChangeExecutorTypeInterceptor implements Interceptor {

	private static final Logger logger = LoggerFactory.getLogger(AutoMapperChangeExecutorTypeInterceptor.class);
	
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		Executor executor = null;
		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
		String originalSql = mappedStatement.getBoundSql(invocation.getArgs()[1]).getSql();
		// 根据ID生成相应类型的sql语句（id需剔除namespace信息）
		String id = StringUtils.substringAfterLast(mappedStatement.getId(), ".") ;
		// 只有sql是空并且是调用AutoMapperRepository对象的方法才会走if里面的方法
		if (StringUtils.isNotBlank(originalSql)) {
			return invocation.proceed();
		}
		
		if (!StringUtils.equalsIgnoreCase("update",id)) {
			return invocation.proceed();
		}
		
		Executor cachingExecutor = (Executor) invocation.getTarget();
		// MetaObject是Mybatis提供的一个的工具类,用于获取属性的值（支持OGNL的方法）
		MetaObject metaExecutor = SystemMetaObject.forObject(cachingExecutor);
		metaExecutor = MetaObjectUtils.getOriginalMetaObject(metaExecutor);
		cachingExecutor = (Executor) metaExecutor.getOriginalObject();
		if (cachingExecutor instanceof CachingExecutor) {
			executor = (Executor) metaExecutor.getValue("delegate");
			if (executor == null) {
				logger.warn("Executor类delegate字段不存在");
				return invocation.proceed();
			}		
		}
		
		if (!(executor instanceof SimpleExecutor)){
			return invocation.proceed();
		}
		//new AutoMapperBatchExecutor替换原来的CachingExecutor里的SimpleExecutor对象，实现批量入库功能
		Configuration configuration = mappedStatement.getConfiguration();
		executor = new AutoMapperBatchExecutor(configuration, executor.getTransaction());
		metaExecutor.setValue("delegate", executor);
        return invocation.proceed();
	}
	
	@Override
	public Object plugin(Object target) {
		if (target == null) {
			return target;
        } 
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {}
}
